iT邦幫忙

2026 iThome 鐵人賽

DAY 3
0
ChatGPT & Codex

我的音樂不該被平台綁架:30 天用 ChatGPT × Codex 打造跨平台 Music Recap系列 第 3

Day 3 | 拿 15,403 筆真實 YouTube Music 紀錄驗收,哪些資料真的能拿來做 Recap?

  • 分享至 

  • xImage
  •  

昨天完成 YouTube Music Takeout 的匯入器後,今天終於把自己的真實資料丟進去驗收。

要做自己的 Music Recap,不能只做到「資料讀得進來」。

真正重要的是:

這些資料到底能不能相信?

哪些欄位可以拿來排名?

哪些欄位有缺?

哪些數字看起來可以算,但其實不能亂算?

所以今天的目標,就是拿真正的 Google Takeout 觀看紀錄完整跑一次,確認目前的資料管線到底能不能支撐後面的 Recap。

結果第一次執行,就直接出事。

我的 YouTube Music 紀錄總共有:

15,403 筆

成功匯入:

0 筆

15,403 筆全部失敗。

這也讓我真正體會到,合成測試通過,不代表真實世界就會乖乖照你的格式走。


先看看我的 Takeout 到底有多少資料

這次拿來驗證的是真正從 Google Takeout 匯出的 YouTube 觀看紀錄。

整份資料共有:

總活動紀錄:26,900
YouTube Music:15,403
一般 YouTube:11,497

這和 Day 1 當時初步分析得到的數量一致。

但第一版匯入器實際處理後,結果卻是:

成功匯入 YouTube Music:0
一般 YouTube:11,497
失敗:15,403

也就是說,程式其實知道哪些紀錄是 YouTube Music。

真正出問題的是時間。


真實資料第一個坑:CST

我的 Takeout 時間長這樣:

2026年9月15日 下午6:52:27 CST

原本的時間處理沒有支援這種格式。

更麻煩的是,CST 本身並不是全球唯一的時區名稱。

不同地區可能用 CST 表示不同的時差。

所以不能直接看到 CST 就武斷認定:

CST = UTC+8

這次我的資料依照實際使用情境,以 +08:00 解讀。

但這個設定必須被明確記錄,而不是藏在程式裡偷偷假設。

這件事看起來只是時間格式問題,但對 Recap 其實很重要。

因為後面很多統計都跟時間直接相關,例如:

  • 哪個月份最常聽歌
  • 哪一天聽最多
  • 最常在凌晨還是晚上聽
  • 聆聽高峰落在哪個時段

如果時區一開始就錯了,後面的圖表再漂亮也沒有意義。


第二個坑:繁體中文不只有上午和下午

解掉時區之後,還有下一層問題。

真實 Takeout 裡會出現:

凌晨
清晨
上午
中午
下午
晚上

例如:

凌晨12:30
清晨5:41
中午12:35
晚上7:43

在 15,403 筆 YouTube Music 活動中,這些時段的分布是:

凌晨:5,058
清晨:1,353
上午:1,211
中午:253
下午:3,374
晚上:4,154

原本沒有完整支援的「凌晨、清晨、中午」,加起來就有 6,664 筆。

所以今天也把這些繁體中文時間格式補完整。

例如:

凌晨12:30 → 00:30
中午12:30 → 12:30
晚上9:30 → 21:30

處理完之後,再重新跑完整份真實資料。


第二次驗收:15,403 筆全部成功

修正時間問題後,結果變成:

項目 結果
所有活動紀錄 26,900
YouTube Music 15,403
一般 YouTube 11,497
無法解析 0
不同 Video ID 1,197

這次 15,403 筆 YouTube Music 活動全部成功保留下來。

目前這批音樂紀錄的時間範圍是:

2026-01-31 ~ 2026-09-15

這也代表目前已經有一份真正經過完整驗收的 YouTube Music 活動資料,可以繼續拿來做後面的統計。

不過其中有一個很重要的限制:

1,197 個 Video ID

不代表:

1,197 首不同歌曲

因為同一首歌可能有很多不同影片,例如:

  • 官方音源
  • MV
  • Live
  • THE FIRST TAKE
  • 不同版本
  • 翻唱

所以目前只能說有 1,197 個不同的影片識別碼。

「這些影片哪些其實代表同一首歌」,會是後面歌曲 Identity 要解決的問題。


114 筆紀錄缺少正常頻道名稱

真實資料也讓我發現 metadata 並不是每筆都完整。

15,403 筆音樂活動裡,有:

114 筆

沒有正常的頻道名稱。

目前採用的原則很保守。

如果同一個 Video ID 的其他活動中,只有一個一致而且可用的頻道名稱,才允許補值。

最後結果:

原始缺頻道:114
成功補回:87
仍然未知:27

剩下的 27 筆集中在兩個 Video ID。

其中一組有 26 筆,另一組只有 1 筆。

這兩組都找不到可靠的頻道名稱可以提供證據,所以最後沒有硬猜。

資料不知道,就是保持不知道。

比填入一個錯誤答案安全得多。


「有標題」不代表真的有歌曲名稱

這 114 筆特殊紀錄還出現另一個有趣的問題。

它們的標題欄位並不是空值。

但內容其實只是:

https://music.youtube.com/watch?v=...

也就是影片網址。

如果只檢查:

標題是不是空的?

那它們全部會被算成「有標題」。

可是網址顯然不能當成正常歌曲名稱。

所以現在會保留原始內容,但把這種情況標記成 URL placeholder,不把它計算成可用標題。

目前真實資料的品質大概是:

欄位 覆蓋率
核心事件資料 15,403 / 15,403,100%
可用原始標題 15,289 / 15,403,99.26%
可用原始頻道 15,289 / 15,403,99.26%
補值後可用頻道 15,376 / 15,403,99.82%
實際播放時間 0 / 15,403,0%

這也是我今天很想確認的一件事。

資料品質不能只寫一句:

完整度 99%

因為不同欄位的完整度完全不同。

真正有意義的是:

哪個欄位?
分子是多少?
分母是多少?

最大的問題:YouTube Music 沒有給我播放秒數

這次完整驗收後,最重要的結果其實不是 15,403 筆成功匯入。

而是確認:

15,403 / 15,403
都沒有實際播放秒數

也就是每一筆紀錄都知道:

  • 什麼時候出現
  • Video ID
  • 顯示標題
  • 頻道
  • 來源網址

但不知道:

這一次到底實際聽了幾秒?

這件事會直接影響後面的 Recap。

因為不能把:

一筆活動紀錄

當成:

完整播放一次

也不能用:

歌曲完整長度 × 出現次數

就宣稱是實際聆聽時間。

更不能因為兩筆紀錄相差四分鐘,就假設上一首歌真的完整播放了四分鐘。

那些都只是推測。


那第一版的總聆聽時間怎麼辦?

這裡最後決定先不要自己發明播放時間。

YouTube Music 官方 Recap 本身會顯示總聆聽時間。

所以第一版會直接把這個數字當成:

platform_provided

也就是:

YouTube Music 官方提供的總聆聽時間

它會和我們自己從 Takeout 算出的統計分開。

例如:

Takeout 可以負責

  • 最常出現的歌曲活動
  • 最常出現的頻道
  • 每月活動次數
  • 每天活動次數
  • 常出現的聆聽時段

YouTube Music 官方 Recap 負責

  • 官方提供的總聆聽時間

第一版暫時不做:

單曲推估聆聽時間
歌曲長度乘播放次數
自行猜測每次播放比例

缺的資料就保持缺失。

這樣至少不會為了讓 Recap 看起來更完整,反而製造一個不存在的精準數字。


那目前可以拿 YouTube Music 做什麼 Recap?

經過今天這次驗收後,目前已經可以比較確定哪些統計是安全的。

例如:

最常出現的音樂活動

可以依照活動次數排序。

但這個數字要稱為:

activity_count

不能直接叫完整播放次數。


最常出現的頻道

可以統計。

但頻道名稱目前還不能直接等於歌手名稱。

例如:

YOASOBI - Topic

很接近歌手概念。

但:

THE FIRST TAKE

或其他上傳頻道就不一定代表歌曲真正的 Artist。

所以「頻道排行」和「歌手排行」也必須分開。


什麼時候最常聽歌

這個現在已經可以算。

因為時間格式已經經過真實資料驗證。

未來可以分析:

  • 哪個月份音樂活動最多
  • 星期幾最常聽
  • 凌晨是不是我的主要聽歌時間
  • 哪個小時活動最密集

這部分不需要播放秒數,也能產生滿有意思的 Recap。


為什麼今天要花一天做這件事?

一開始看起來,今天好像只是在修時間格式。

但真正完成的事情其實是:

我終於知道這 15,403 筆資料哪些能信,哪些不能信。

現在已經可以明確知道:

事件時間 → 可用
Video ID → 可用
活動次數 → 可用
頻道 → 大部分可用
標題 → 大部分可用
實際播放秒數 → 不可用
歌曲 Identity → 尚未完成
Artist Identity → 尚未完成

這會直接決定之後 Recap 的每一個指標到底能不能顯示。

否則很容易做出一個看起來很厲害的年度回顧,結果底下其實混著錯誤假設。


Day 3 的結果

今天真正完成的是:

YouTube Music 真實 Takeout
↓
26,900 筆活動完整解析
↓
15,403 筆音樂活動成功保留
↓
確認 metadata 缺口
↓
有證據的資料才補值
↓
確認沒有逐筆實際播放時間
↓
知道哪些資料可以拿去做 Recap

所以現在不只是「我可以讀 YouTube Music」。

而是開始建立一個更重要的東西:

每個 Recap 數字,都要知道自己是怎麼來的。

下一步,就是把這些規則真正變成 Recap 指標。

例如一個排名到底是:

activity_count

還是:

observed_played_ms

或是:

platform_provided

等這些統計口徑定下來後,就可以開始做第一份真正屬於自己的 YouTube Music Recap。

另外回覆前一篇的留言
Q:
把「不知道播放多久」和「播放零秒」分開,這個細節很容易被忽略。好奇之後產生 Music Recap 時,會不會同時顯示資料覆蓋率或可信程度?不然漂亮的排行可能會讓人忘記原始資料其實有缺口。
A:
有,這個問題我也有考慮到,所以目前資料模型除了把 0 和 unknown 分開,也會計算 duration_coverage。之後做 Recap 時,像 YouTube Music 這種沒有每筆播放秒數的來源且之後沒有解決的辦法的話,排行榜會明確標示是依「活動次數」計算,不會包裝成完整播放次數或真實收聽時間。後面做 Web App 時,我也打算把資料覆蓋率與可信度一起呈現,避免只給一個很漂亮但來源其實有缺口的排行。


上一篇
Day 2|把我的 YouTube Music 紀錄挖出來:Google Takeout 到底給了什麼?
下一篇
Day 4|YouTube Music 沒有播放秒數,那 Recap 還能算什麼?
系列文
我的音樂不該被平台綁架:30 天用 ChatGPT × Codex 打造跨平台 Music Recap5
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言